use business::{business_reg, handle_channel_start, user_login_sip_passwd_logic};
use persistence::sqlx_p::DB;
use switch::{sip2::manage::listen_device, DialogEvent, DIALOG_DISTIBUTE, USER_HOLD};
use tokio::signal::unix::{signal, SignalKind};
use tools::global_defin::tokio_runtime::get_rt;
use tracing::{info, span, Instrument, Level};

fn main() {
	let rt = tools::global_defin::tokio_runtime::get_rt();
	let _rt_guard = rt.enter();
	let _log = tools::global_defin::trace_log::init_tracing_log();
	let _pool = &DB.pool;

	listen_device(&handle_channel_start, &business_reg, |s| {
		Box::pin(user_login_sip_passwd_logic(s))
	});

	let span = span!(Level::ERROR, "signal");
	rt.spawn(handle_signal().instrument(span));

	std::thread::park();
}

///处理收到的各种信号,目前只处理ctrl+c(3) SIGTERM(15)(直接使用kill)..SIGUSR1(10)..SIGUSR2(12)
async fn handle_signal() {
	let mut s3 = signal(SignalKind::interrupt()).unwrap();
	let mut s15 = signal(SignalKind::terminate()).unwrap();
	let mut s10 = signal(SignalKind::user_defined1()).unwrap();
	let mut s12 = signal(SignalKind::user_defined2()).unwrap();

	loop {
		tokio::select! {
			_c = s3.recv() => {
				#[cfg(debug_assertions)]
				exit_by_debug().await;

				#[cfg(not(debug_assertions))]
				info!("收到ctrl-c信号...跳过");
			}
			_c = s15.recv() => {
				clear_for_close().await;
				std::process::exit(0);
			}
			_c = s10.recv() => {
				handle_signal_user1().await;
			}
			_c = s12.recv() => {
				handle_signal_user2().await;
			}
		}
	}
}

///当代码处于debug模式时,收到ctrl-c信号,调用此方法退出.
#[allow(unused)]
#[inline]
async fn exit_by_debug() {
	info!("收到ctrl-c信号...退出.");
	clear_for_close().await;
	std::process::exit(0);
}

///打印出当前存在的对话信息
async fn handle_signal_user1() {
	info!("收到SIGUSR1信号");
	let _ = &DIALOG_DISTIBUTE
		.get()
		.unwrap()
		.try_send(DialogEvent::ShowDialogs);
}

///打印当前注册用户相关信息
async fn handle_signal_user2() {
	info!("收到SIGUSR2信号");

	get_rt().spawn(async {
		let h = USER_HOLD.read().await;
		info!("当前注册用户:{}", h.len());
		for (_, v) in h.iter() {
			info!("用户:{:?}", v);
		}
	});
}

async fn clear_for_close() {
	//TODO 收到退出信号,退出前要干点什么
	info!("收到关闭信号");
}
